package org.zongf.learn.grpc.starter;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.AbstractBlockingStub;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.zongf.learn.grpc.starter.config.GrpcClientConfig;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zongf
 * @since 2023-07-10
 **/
@Slf4j
public abstract class AbsGrpcRmtService<S extends AbstractBlockingStub<S>> implements  InitializingBean {

    private List<S> stubList = new ArrayList<>();

    private AtomicInteger idx = new AtomicInteger(0);

    @Autowired
    private GrpcClientConfig grpcClientConfig;

    public S getBlockingStub() {
        // 轮询
        int i = idx.incrementAndGet() % stubList.size();
        if (i == 0) {
            idx.set(0);
        }
        return stubList.get(i);
    }

    // 创建 BlockingStub
    protected abstract S newBlockingStub(ManagedChannel managedChannel);

    // 获取服务名称
    protected abstract String getServiceName();

    // 初始化连接
    @Override
    public void afterPropertiesSet() throws Exception {
        String[] hosts = grpcClientConfig.getClientMap().get(getServiceName());
        log.info("grpc client, serverName:{}, host:{}", getServiceName(), hosts);

        for (String host : hosts) {
            String[] array = host.split(":");
            String ip = array[0];
            Integer port = Integer.parseInt(array[1]);
            try {
                ManagedChannel managedChannel = ManagedChannelBuilder
                        .forAddress(ip, port)
                        .usePlaintext()
                        .build();

                stubList.add(newBlockingStub(managedChannel));
            } catch (Throwable exception) {
                log.error("服务连接失败, instance:{}", host);
            }
        }
    }

}
